#pragma once

#include "StdAfx.h"
#include "../dep/include/openssl/bn.h"

namespace Crypt {

class BigNumber
{
public:
        BigNumber();
        BigNumber(const BigNumber& bn);
        BigNumber(uint32);
        BigNumber(const uint8* pBinary, uint32 length);
        BigNumber(std::vector<uint8>& vBinary);
        BigNumber(std::string hexString);
        ~BigNumber();

        void SetDword(uint32);
        void SetQword(uint64);
        void SetBinary(const uint8* bytes, int len);
        void SetHexStr(const char* str);

        void SetRand(int numbits);

        BigNumber operator=(const BigNumber& bn);

        BigNumber operator+=(const BigNumber &bn);
        BigNumber operator+(const BigNumber &bn)
        {
                BigNumber t(*this);
                return t += bn;
        }
        BigNumber operator-=(const BigNumber& bn);
        BigNumber operator-(const BigNumber& bn)
        {
                BigNumber t(*this);
                return t -= bn;
        }
        BigNumber operator*=(const BigNumber& bn);
        BigNumber operator*(const BigNumber& bn)
        {
                BigNumber t(*this);
                return t *= bn;
        }
        BigNumber operator/=(const BigNumber& bn);
        BigNumber operator/(const BigNumber& bn)
        {
                BigNumber t(*this);
                return t /= bn;
        }
        BigNumber operator%=(const BigNumber& bn);
        BigNumber operator%(const BigNumber& bn)
        {
                BigNumber t(*this);
                return t %= bn;
        }

        BigNumber ModExp(const BigNumber& bn1, const BigNumber& bn2);
        BigNumber Exp(const BigNumber&);

        const int GetNumBytes(void) const;

        struct bignum_st *BN() { return _bn; }

        const uint32 AsDword() const;
        const uint8* AsByteArray() const;
        const std::vector<uint8> AsVector() const;

        const char* AsHexStr();
        const char* AsDecStr();

private:
        struct bignum_st* _bn;
        mutable uint8* _array;
};

};